package yf.mall.service.impl;

import com.aliyuncs.utils.IOUtils;
import com.yf.utils.DateUtil;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.RequestParam;
import yf.mall.common.Const;
import yf.mall.dao.*;
import yf.mall.entity.AreaEntity;
import yf.mall.entity.LevelEntity;
import com.yf.entity.TokenEntity;
import com.yf.entity.WxUser;
import com.yf.service.impl.BaseServiceImpl;
import yf.mall.enums.AccountRecordBusEnum;
import yf.mall.enums.AccountRecordStatusEnum;
import yf.mall.enums.AccountTypeEnum;
import yf.mall.enums.UserStatusEnum;
import com.yf.response.RRException;
import com.yf.service.TokenService;
import com.yf.service.WxWebService;
import yf.mall.service.NoticeService;
import yf.mall.service.UserService;
import yf.mall.vo.UserEntityVo;
import yf.mall.vo.UserVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.*;
import java.math.BigDecimal;
import java.net.URL;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Random;

import yf.mall.entity.UserEntity;
import org.springframework.transaction.annotation.Transactional;

import javax.imageio.ImageIO;
import javax.servlet.http.HttpServletResponse;

/**
 * 用户Service实现类
 *
 * @author hxf
 * @email 505860922@qq.com
 * @date Tue Aug 27 18:12:02 CST 2019
 */
@Service
public class UserServiceImpl extends BaseServiceImpl<UserEntity> implements UserService {

    private UserDao userDao;

    @Autowired
    private WxWebService wxWebService;

    @Autowired
    private TokenService tokenService;


    @Autowired
    public void setDao(UserDao userDao) {
        this.userDao = userDao;
        super.setBaseDao(userDao);
    }


    /**
     * 内部方法
     **/

    private void updateTeam(UserEntity user, UserEntity topUser) {
        String oldTeam = user.getTeam();
        String newTeam = user.getId() + "/";
        //设置Team
        if (topUser.getTeam() != null) {
            newTeam = topUser.getTeam() + newTeam;
        } else {
            newTeam = "/" + newTeam;
        }
//        user.setTeam(newTeam);
        userDao.update(user);
        //更新下面团队的前缀
        if (oldTeam != null) {
            String oldTCode = user.getTCode();
            String newTCode = oldTCode;
            if (topUser.getTCode() != null) {
                newTCode = topUser.getTCode();
            }
            userDao.updateTeam(oldTCode, newTCode, oldTeam, newTeam);
        }
    }


    /**
     * 外部方法实现
     **/

    @Override
    public List<UserVo> queryListVo(UserVo userVo) {
        return userDao.queryListVo(userVo);
    }

    @Override
    public UserVo getVo(Long id) {
        return userDao.getVo(id);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public UserVo updateVo(UserVo userVo) {
        //验证手机号码
        validatePhone(userVo.getUser().getMobile(), userVo.getUser());
        //判断上级
        String topUserCode = userVo.getTopUser().getCode();
        if (topUserCode == null) {
            throw new RRException("请填写上级");
        }
        UserEntity topUser = userDao.findByCode(topUserCode);
        if (topUser == null) {
            throw new RRException("上级编号无效!");
        }
        userVo.getUser().setPid(topUser.getId());
        //判断推荐人
        String refererCode = userVo.getReferer().getCode();
        if (refererCode != null) {
            UserEntity referer = userDao.findByCode(refererCode);
            if (referer != null) {
                userVo.getUser().setRid(referer.getId());
            }
        }

        //更新用户基本信息
        update(userVo.getUser());
        //更新树
        updateTeam(userVo.getUser(), topUser);
        return userVo;
    }

    @Override
    public UserEntity findByCode(String code) {
        return userDao.findByCode(code);
    }

    @Override
    public UserEntity findByMobile(String mobile) {
        return userDao.findByMobile(mobile);
    }

    @Override
    public void validateUser(UserEntity fromUser, UserEntity toUser) {
        //验证账户
        String fromUserName = fromUser.getName();
        String fromUserCode = fromUser.getCode();
//        if (fromUserCode == null || fromUserCode.trim().equals("")) {
//            throw new RRException("请填写转货人信息!");
//        }
        if (fromUserCode != null && !fromUserCode.trim().equals("")) {
            fromUser = userDao.findByCode(fromUserCode);
            if (fromUser == null || !fromUser.getName().equals(fromUserName)) {
                throw new RRException("转货人信息不匹配!");
            }
        }
        String toUserName = toUser.getName();
        String toUserCode = toUser.getCode();
        if (toUserCode == null || toUserCode.trim().equals("")) {
            throw new RRException("请填写接收人信息!");
        }
        toUser = userDao.findByCode(toUserCode);
        if (toUser == null || !toUser.getName().equals(toUserName)) {
            throw new RRException("接收人信息不匹配!");
        }

    }

    @Override
    public List<UserVo> findByNameOrCodeOrMobile(String param) {
        return userDao.findByNameOrCodeOrMobile(param);
    }


    @Override
    public List<UserVo> findByTop(Long userId, Integer type) {
        List<UserVo> results = new ArrayList<>();

        List<UserVo> userVos = this.userDao.findByUserId(userId);


        results.addAll(userVos);
        // 递归查找下级
        if (type != null) {
            findByList(results, userVos, type);
        }
        return results;
    }


    private void findByList(List<UserVo> results, List<UserVo> userVos, int type) {
        if (userVos.size() > 0 && type != 0) {
            List<UserVo> tems = userDao.findList(userVos);
            results.addAll(tems);
            type = type - 1;
            findByList(results, tems, type);
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public TokenEntity wxLogin(WxUser wxUser, Long topUserId, Boolean register) {
        TokenEntity tokenEntity;

        //判断用户是否存在
        String wxId = wxUser.getOpenId();
        UserEntity userEntity = userDao.findByWxId(wxId);
        //更新unionId
        if (wxUser.getUnionId() != null && !wxUser.getUnionId().equals("")) {
            UserEntity tem = userDao.findByWxId(wxUser.getUnionId());
            if (userEntity != null && tem == null) { //unionid后面录入
                userEntity.setUnionId(wxUser.getUnionId());
            } else {
                userEntity = tem;
            }
        }


        //用户不存在
        if (userEntity == null) {
            //如果可以注册直接注册
            if (register) {
                userEntity = register(wxUser.getOpenId(), wxUser.getUnionId(), wxUser.getNickName(), wxUser.getHeadImgUrl(), null, null, topUserId);
            } else {
                return null;
            }
        } else {
            //只有没有设置名称的时候更新名称
            if (userEntity.getName() == null || userEntity.getName().equals("")) {
                userEntity.setName(wxUser.getNickName());
            }
            //没有绑定手机号 重新绑定上级
            if(userEntity.getMobile()==null&&topUserId!=null){
                UserEntity topUser = userDao.get(topUserId);
                if(topUser!=null){
                    userEntity.setPid(topUserId);
                    userEntity.setRid(topUserId);
                    updateTeam(userEntity,topUser);
                }
            }
            userEntity.setAvatar(wxUser.getHeadImgUrl());
            userDao.update(userEntity);
        }
        tokenEntity = tokenService.createToken(userEntity.getId());
        return tokenEntity;
    }

    //TODO 验证验证码
    @Override
    public TokenEntity phoneLogin(String avatar, String name, String openId, String unionId, String phone, String captcha, Long topUserId, Boolean register) {
        UserEntity userEntity = userDao.findByMobile(phone);
        if (userEntity == null) {
            //如果不可以注册
            if (!register) {
                return null;
            }
            //直接注册
            userEntity = register(openId, unionId, name, avatar, phone, captcha, topUserId);
        } else {
            //只有没有设置名称的时候更新名称
            if (userEntity.getName() == null || userEntity.getName().equals("")) {
                userEntity.setName(name);
            }
            userEntity.setAvatar(avatar);
            userDao.update(userEntity);
        }
        TokenEntity tokenEntity = tokenService.createToken(userEntity.getId());
        return tokenEntity;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public UserEntity register(String openId, String unionId, String name, String avatar, String phone, String captcha, Long topUserId) {
        if (topUserId == null) {//不存在上家  上家设置为
            throw new RRException("请扫推荐人的二维码注册");
        }
        UserEntity topUser = get(topUserId);
        if (topUser == null) {
            throw new RRException("推荐人不存在!");
        }
        LevelEntity levelEntity = levelDao.findBase();
        UserEntity userEntity = new UserEntity(phone, openId, unionId, avatar, name, createCode(topUser.getTCode()), topUser.getTCode(), topUser.getId(), topUser.getId(), null, levelEntity.getId(), new Date(), UserStatusEnum.ACTIVE.getIndex());
        save(userEntity);
        updateTeam(userEntity, topUser);
        //通知
        noticeService.sendUserIn(topUser.getOpenId(), userEntity.getName(), "");
        return userEntity;
    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    public UserEntity wgRegister(String unionId, String name, String code, String tCode, String avatar, String phone, Long topUserId, String topCode) {
        UserEntity userEntity = null;
        if (topCode == null || ("").equals(topCode)) {
            return null;
        }
        //查找上级
        UserEntity topUser = userDao.findByCode(topCode);
        if (null == topUser) {
            return null;
        }
        topUserId = topUser.getId();
        LevelEntity levelEntity = levelDao.findBase();
        if (unionId != null) {
            userEntity = userDao.findByWxId(unionId);
            if (null == userEntity) {
                userEntity = new UserEntity(phone, null, unionId, avatar, name, code, tCode, topUserId, topUserId, null, levelEntity.getId(), new Date(), UserStatusEnum.ACTIVE.getIndex());
                save(userEntity);
            }
        }
        return userEntity;
    }

    @Override
    public UserEntity register(String openId, Long topUserId) {
        WxUser wxUser = wxWebService.getWxUserBySdk(openId);
        //判断用户是否存在
        String wxId = wxUser.getOpenId();
        UserEntity userEntity = userDao.findByWxId(wxId);
        //更新unionId
        if (wxUser.getUnionId() != null && !wxUser.getUnionId().equals("")) {
            UserEntity tem = userDao.findByWxId(wxUser.getUnionId());
            if (userEntity != null && tem == null) { //unionid后面录入
                userEntity.setUnionId(wxUser.getUnionId());
            } else {
                userEntity = tem;
            }
        }
        if (userEntity != null) {
            userEntity.setOpenId(wxUser.getOpenId());
            userEntity.setUnionId(wxUser.getUnionId());
            update(userEntity);
            return userEntity;
        }
        //如果不存在则注册
        userEntity = register(openId, wxUser.getUnionId(), wxUser.getNickName(), wxUser.getHeadImgUrl(), null, null, topUserId);
        return userEntity;
    }

    @Autowired
    private NoticeService noticeService;

//    public static void main(String[] args) {
//        UserEntity te = null;
//        UserEntity tt = null;
//        System.out.println(te = tt);
////        System.out.println(System.currentTimeMillis());
//    }
public static void main(String[] args) throws Exception {
    SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
    Date date = format.parse("2020-02-02");
    Date formats = format.parse("2020-03-02");

    System.out.println( DateUtil.getDays(date,formats));

}


    @Autowired
    private LevelDao levelDao;

    private String createCode(String tCode) {
        Random random = new Random();
        String code = tCode + random.nextInt(999999);
        int count = 0;
        while (findByCode(code) != null) {
            count++;
            code = tCode + random.nextInt(999999);
            if (count > 5) {
                throw new RRException("生成代理失败");
            }
        }
        return code;
    }

    //团队
    private void createTeam(UserEntity userEntity, UserEntity topUser) {
        String team = userEntity.getTeam() + topUser.getId() + "/";
        userEntity.setTeam(team);
        update(userEntity);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public UserEntity update(Long userId, String phone, String password, String name, Boolean async) {
        UserEntity userEntity = userDao.get(userId);


        if (async == null || !async) {
            userEntity.setPassword(password);
            userEntity.setName(name);
            validatePhone(phone, userEntity);
            userEntity.setMobile(phone);
            userDao.update(userEntity);
            return userEntity;
        } else {//同步账号  后期去掉 TODO 就是切换账号
            if (userEntity.getMobile() != null && !userEntity.getMobile().equals("")) {
//                throw new RRException("请勿重复同步!");
                return userEntity;
            }

            UserEntity tem = userDao.findByMobile(phone);
            if (tem == null) {
                throw new RRException("手机号码不存在!");
            }

            if (tem.getOpenId() != null && !tem.getOpenId().equals("")) {
                throw new RRException("账号已被同步!");
            }
            tem.setAvatar(userEntity.getAvatar());
            tem.setName(userEntity.getName());
            tem.setUnionId(userEntity.getUnionId());
            tem.setOpenId(userEntity.getOpenId());
            userDao.update(tem);
            userEntity.setOpenId("");
            userEntity.setUnionId("");
            userDao.update(userEntity);//直接删除
            return tem;
        }


    }

    @Override
    public void validatePhone(String phone, UserEntity userEntity) {
        try {
            UserEntity tem = userDao.findByMobile(phone);
            if (tem != null && userEntity != null && !tem.getId().equals(userEntity.getId())) {
                throw new RRException("手机号码已经被占用!");
            }
            if (tem != null && userEntity == null) {
                throw new RRException("手机号码已经被占用");
            }
        } catch (Exception e) {
            throw new RRException("手机号码已经被占用!");
        }
    }

    @Override
    public void validateUser(Long userId) {
        UserEntity userEntity = userDao.get(userId);
        if (userEntity.getStatus() != null && userEntity.getStatus().equals(UserStatusEnum.BAN.getIndex())) {
            throw new RRException("已禁止操作");
        }
    }

    @Override
    public UserEntity getLvTopUser(Long userId) {
        UserEntity userEntity = get(userId);
        if (userEntity == null) {
            throw new RRException("用户:" + userId + "不存在");
        }
        LevelEntity userLv = levelDao.findByUserId(userId);
        UserEntity topUser = get(userEntity.getPid());
        while (topUser != null) {
            LevelEntity topLv = levelDao.findByUserId(topUser.getId());
            //上级是公司或者高级别用户
            if (topUser.getId().equals(Const.ADMIN_ID) || topLv.getLv() < userLv.getLv()) {
                break;
            }
            topUser = get(topUser.getPid());
        }
        return topUser;
    }

    @Override
    public UserEntity findByWxId(String wxId) {
        return userDao.findByWxId(wxId);
    }

    @Autowired
    private AccountRecordDao accountRecordDao;

    /**
     * 查询当前用户信息并查询当前用户的总粉丝数，总代理数，总佣金
     *
     * @param userId
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public UserEntityVo findNowUserInfo(Long userId) {
        UserEntityVo userEntityVo = new UserEntityVo();
        UserEntity userEntity = this.userDao.get(userId);
        userEntityVo.setUserEntity(userEntity);
        Long lv = this.levelDao.findBase().getId();
//      获取粉丝数
        // 获取总粉丝数
        List<UserEntity> userEntities = this.userDao.findByTop(userId);
        List<UserEntity> results = new ArrayList<>();
        List<UserEntity> userEntityList = new ArrayList<>();


        results.addAll(userEntities);
        results = findByLists(results, userEntities);

        for (UserEntity result : results) {
            if (result.getLevelId() == lv) {
//                System.out.println(result.getName()+result.getLevelId());
                continue;
            }
            userEntityList.add(result);
        }
        userEntityVo.setAgentNum(userEntityList.size());
        userEntityVo.setFansNum(results.size() - userEntityList.size());

        //TODO
        BigDecimal totalShareDone = this.accountRecordDao.total( Const.ADMIN_ID, userId,AccountTypeEnum.CASH.getIndex(), AccountRecordStatusEnum.DONE.getIndex(),null, AccountRecordBusEnum.SHARE_REWARD.getIndex());
        BigDecimal totalAreaDone = this.accountRecordDao.total( Const.ADMIN_ID, userId,AccountTypeEnum.CASH.getIndex(), AccountRecordStatusEnum.DONE.getIndex(),null, AccountRecordBusEnum.AREA_REWARD.getIndex());
        BigDecimal totalShareWait = this.accountRecordDao.total( Const.ADMIN_ID, userId,AccountTypeEnum.CASH.getIndex(), AccountRecordStatusEnum.WAIT.getIndex(),null, AccountRecordBusEnum.SHARE_REWARD.getIndex());
        BigDecimal totalAreaWait = this.accountRecordDao.total( Const.ADMIN_ID, userId,AccountTypeEnum.CASH.getIndex(), AccountRecordStatusEnum.WAIT.getIndex(),null,AccountRecordBusEnum.AREA_REWARD.getIndex());
        BigDecimal bigDecimal = this.accountRecordDao.totalByInfo( Const.ADMIN_ID,userId, AccountTypeEnum.CASH.getIndex(), AccountRecordStatusEnum.DONE.getIndex(), AccountRecordBusEnum.TRANSFER.getIndex(), "%" + Const.REWARD_TRANSFER + "%");
        BigDecimal decimal = this.accountRecordDao.totalByInfo( Const.ADMIN_ID,userId, AccountTypeEnum.CASH.getIndex(), AccountRecordStatusEnum.WAIT.getIndex(), AccountRecordBusEnum.TRANSFER.getIndex(), "%" + Const.REWARD_TRANSFER + "%");
        if (bigDecimal == null) {
            bigDecimal = BigDecimal.ZERO;
        }
        if (decimal == null) {
            decimal = BigDecimal.ZERO;
        }
        if (totalShareDone == null) {
            totalShareDone = BigDecimal.ZERO;
        }

        if (totalShareWait == null) {
            totalShareWait = BigDecimal.ZERO;
        }

        if (totalAreaDone == null) {
            totalAreaDone = BigDecimal.ZERO;
        }
        if (totalAreaWait == null) {
            totalAreaWait = BigDecimal.ZERO;
        }
        totalShareDone = totalShareDone.add(bigDecimal);
        totalShareDone = totalShareDone.add(totalAreaDone);
        totalShareWait = totalShareWait.add(decimal);
        totalShareWait = totalShareWait.add(totalAreaWait);
        BigDecimal backDone = this.accountRecordDao.total(userId,Const.ADMIN_ID,  AccountTypeEnum.CASH.getIndex(), AccountRecordStatusEnum.DONE.getIndex(),Const.REWARD_TRANSFER, AccountRecordBusEnum.BACK.getIndex());
        if (backDone != null) {
            totalShareDone = totalShareWait.subtract(backDone);
        }


        userEntityVo.setTotalDone(totalShareDone);
        userEntityVo.setTotalWait(totalShareWait);
        return userEntityVo;
    }


    private List<UserEntity> findByLists(List<UserEntity> results, List<UserEntity> userEntities) {
        if (userEntities.size() > 0) {
            List<UserEntity> tems = userDao.findByList(userEntities);
            results.addAll(tems);
            findByLists(results, tems);
        }
        return results;
    }


    @Autowired
    private AreaDao areaDao;

    @Value("${AUTH-IMG}")
    private String authImg;

    @Override
    public void createAuthImg(Long userId, HttpServletResponse response) {
        UserEntity userEntity = get(userId);
        try {
            URL url = new URL(authImg);
            BufferedInputStream inputStream = new BufferedInputStream(url.openStream());
            BufferedImage bufferedImage = ImageIO.read(inputStream);
            Graphics g = bufferedImage.getGraphics();
            g.setColor(Color.BLACK);
            g.setFont(new Font("宋体", Font.BOLD, 30));
            //名字
            g.drawString(userEntity.getName(), 420, 625);
            //手机号
            g.drawString(userEntity.getMobile(), 420, 700);
            //区域代理 TODO 搜索区域代理
            List<AreaEntity> areaEntityList = this.areaDao.findByUserId(userEntity.getId());
            if (!areaEntityList.isEmpty()) {

                g.drawString(areaEntityList.get(0).getName() + "区域代理", 420, 866);

            }//编号
            g.drawString(userEntity.getCode(), 420, 950);
            //级别
            LevelEntity levelEntity = levelDao.findByUserId(userId);
            g.drawString(levelEntity.getName(), 420, 1026);
            //时间
            g.drawString(DateUtil.dateFormat("yyyy-MM-dd", userEntity.getTime()), 290, 1135);
            g.dispose();
            ByteArrayOutputStream out = new ByteArrayOutputStream();
            ImageIO.write(bufferedImage, "jpg", response.getOutputStream());
            IOUtils.closeQuietly(response.getOutputStream());
        } catch (Exception e) {
            e.printStackTrace();
        }

    }
}
